#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "main.h"

List* slist_add(List *list, Pointer data, char* key)
{
	List* newlist;
    newlist = (List*) malloc(sizeof(List));
    newlist->key  = key;
    newlist->data = data;
    newlist->next = NULL;
    return newlist;
}
List* slist_destroy(List *list)
{
		List *buf1;
		List *buf2;
		buf1 = buf2 = list;
		while (buf1->next != NULL)
		{
		buf2->next = buf1;
		free(buf1);
		buf1 = buf2;
		}
}

void slist_elem(List *list, void (*function)(char *key, Pointer data))
{
	while(list != NULL)
	{
		function(list->key, list->data);
		list = list->next;
	}
}


void* ht_destroy(Pointer *_self)
{
        struct HashTable* self = _self;
        int i;
        for(i=0; i<self->size; i++)
        {
         delete(self->table[i]);
        }
        free(self->table);
        free(self);
}


HashTable* ht_init(size_t size, HashFunction hf, Destructor dtor)
{
	HashTable *ht;
	size_t i;
        ht = (HashTable*)malloc(sizeof(HashTable));
        ht->table = (List**)malloc(sizeof(List)*size);
        ht->size = size;

        if(hf != NULL){
                ht->hashfunc = hf;
        }
		else
		{
        ht->hashfunc = jenkins_one_at_a_time_hash;
        }

        if(dtor != NULL)
		{
            ht->dtor = dtor;
        }
		else
		{
            ht->dtor = NULL;
        }

        for(i = 0; i < ht->size; i++)
		{
            ht->table[i] = NULL;
        }
		return ht;
}

void ht_destroy(Hashtable *ht)
	int i;
List *list1, *list2;

if(ht->dtor != NULL)
{
for(i = 0; i < ht->size; i++)
	ht->dtor(ht->table[i]->data);
}
else
{
	for(i = 0; i < ht->size; i++)
		list1 = list2 = ht->table[i];
	free(ht->table[i]);
	if (list2 != NULL)
	{
		while (list1 != NULL)
		{
			list2 = list1->next;
			free(list1->next);
			list1 = list2;
		}
		free(ht->table[i]);
	}
	free(ht->table);
		free(ht);


Pointer ht_get(HashTable *ht, char *key)
{
        size_t i;
        List * buf;

        i = ht->hashfunc(key) % ht->size;
        buf = ht->table[i];
        
		while(buf != NULL)
        {
                if(strcmp(buf->key, key) == 0)
                {
                        return buf->data;
                }
                buf = buf->next;
        }
        return NULL;